import sys
from bin import texturefiller, Image
from PyQt5.QtWidgets import QApplication, QMainWindow, QFileDialog, QLabel, QMessageBox, QInputDialog
from PyQt5.QtGui import QPixmap, QImage, QPainter
from PyQt5.QtCore import Qt, QPoint, pyqtSlot, QTimer, QEventLoop
from bin.Error import *
import os, cv2, random
import numpy as np
from db import texture_db, edge_db, point_db
import time
import shutil


class MainWindow(QMainWindow, texturefiller.Ui_TextureFillClass):

    def __init__(self, parent=None):
        QMainWindow.__init__(self, parent)
        self.setupUi(self)
        self.img = Image.Image()
        self.qLabel = QLabel()
        self.qLabel.setAlignment(Qt.AlignBaseline | Qt.AlignLeft)
        self.qPixmap = QPixmap()
        self.lastPoint = QPoint(0, 0)
        self.endPoint = QPoint(0, 0)
        self.isDrawing = False  # 标志是否正在绘图
        self.isSelect = True  # 是否能够选择
        self.isGradient = self.actiongradient.isChecked()  # 是否能够显示梯度
        self.isPoint = self.actionbatch.isChecked()  # 是否能够标注
        self.isFilling = self.actionfill.isChecked()  # 是否能填充
        self.isSaveTwinEdge = self.actionisSaveTwinEdge.isChecked()  # 是否保存双边缘
        self.saveExtension = '.png'
        self.boundarType = 0
        self.init_folders()

    def init_folders(self):
        '''
        Initiate the necessary folders
        :return:
        '''
        if not os.path.exists(os.path.join(self.img.saveDir, 'texture')):
            os.makedirs(os.path.join(self.img.saveDir, 'texture'))
        if not os.path.exists(os.path.join(self.img.saveDir, 'pure')):
            os.makedirs(os.path.join(self.img.saveDir, 'pure'))
        if os.path.exists('process'):
            shutil.rmtree('process')
            os.makedirs('process/texture')
            os.makedirs('process/pure')
        else:
            os.makedirs('process/texture')
            os.makedirs('process/pure')

    def save_result(self, dir):
        '''
        Save generated texture and pure color image into the save's folders
        :param dir:
        :return:
        '''
        t = int(time.time())
        (filename, extension) = os.path.splitext(self.img.filename)
        cv2.imwrite(os.path.join(dir, 'texture', '%s_%s%s' % (filename, t, self.saveExtension)),
                    cv2.cvtColor(self.img.image, cv2.COLOR_RGB2BGR))
        cv2.imwrite(os.path.join(dir, 'pure', '%s_%s%s' % (filename, t, '.png')),
                    cv2.cvtColor(self.img.pureImage, cv2.COLOR_RGB2BGR))

    def image_update(self):
        '''
        When the image is changed, the information about this image will be updated
        :return:
        '''
        # update image
        self.qImage = QImage(self.img.image.data, self.img.width, self.img.height,  # 创建QImage格式的图像，并读入图像信息
                             self.img.width * self.img.depth,
                             QImage.Format_RGB888)
        self.scrollArea.setWidget(self.qLabel)
        self.qPixmap = QPixmap.fromImage(self.qImage)
        self.qLabel.setPixmap(self.qPixmap)
        # update next label text
        self.img_size.setText("%s × %s" % (self.img.height, self.img.width))
        imgId = self.img.imageList.index(self.img.filename) + 1
        if imgId < len(self.img.imageList):
            self.next.setText(self.img.imageList[imgId])
        else:
            self.next.setText("None")

    def fill_image(self, texture_path, xy, rgb, isTwinEdge=False):
        '''
        Fill the image with texture
        :param texture_path:
        :param xy:
        :param rgb:
        :return:
        '''
        texture = cv2.imread(texture_path)
        print(texture_path)
        texture = cv2.cvtColor(texture, cv2.COLOR_BGR2RGB)
        texture = texture[0: self.img.height, 0:self.img.width, :]

        color = (1, 1, 1)
        white = (255, 255, 255)
        result = cv2.imread(self.img.path)
        result = cv2.cvtColor(result, cv2.COLOR_BGR2RGB)
        # if isTwinEdge:
        #     mask = np.zeros([self.img.height + 2, self.img.width + 2], np.uint8)
        #     cv2.floodFill(self.img.pureImage, mask, xy, white, cv2.FLOODFILL_FIXED_RANGE)
        #     mask = np.zeros([self.img.height + 2, self.img.width + 2], np.uint8)
        #     cv2.floodFill(result, mask, xy, white, cv2.FLOODFILL_FIXED_RANGE)
        # mask = np.zeros([self.img.height + 2, self.img.width + 2], np.uint8)
        # cv2.floodFill(self.img.pureImage, mask, xy, rgb, cv2.FLOODFILL_FIXED_RANGE)
        # t1 = time.time()
        mask = np.zeros([self.img.height + 2, self.img.width + 2], np.uint8)
        cv2.floodFill(result, mask, xy, color, cv2.FLOODFILL_FIXED_RANGE)

        pure = np.ones(self.img.image.shape, np.uint8)  # 输出一张图片，属性为高400，宽400，通道3
        rgb = (round(rgb[0], 0), round(rgb[1], 0), round(rgb[2], 0))
        rgb = np.array(rgb, dtype='uint8')
        pure *= rgb
        if isTwinEdge:
            # R 表示 右边pad
            r = np.pad(result, ((0, 0), (0, 1), (0, 0)), 'edge')[:, 1:, :] == color
            l = np.pad(result, ((0, 0), (1, 0), (0, 0)), 'edge')[:, :-1, :] == color
            t = np.pad(result, ((1, 0), (0, 0), (0, 0)), 'edge')[:-1, :, :] == color
            b = np.pad(result, ((0, 1), (0, 0), (0, 0)), 'edge')[1:, :, :] == color
            r_t = np.pad(result, ((1, 0), (0, 1), (0, 0)), 'edge')[:-1, 1:, :] == color
            l_t = np.pad(result, ((1, 0), (1, 0), (0, 0)), 'edge')[:-1, :-1, :] == color
            l_b = np.pad(result, ((0, 1), (1, 0), (0, 0)), 'edge')[1:, :-1, :] == color
            r_b = np.pad(result, ((0, 1), (0, 1), (0, 0)), 'edge')[1:, 1:, :] == color
            boundary = result == white

            boundary = boundary * (r + l + t + b + r_t + l_t + l_b + r_b)
            result = result == color
            # if random.random() < .5:
            result = result + boundary
        else:
            result = result == color
        try:
            if "planar" in texture_path:
                self.img.pureImage = np.where(result, texture, self.img.pureImage)
            else:
                self.img.pureImage = np.where(result, pure, self.img.pureImage)
            self.img.image = np.where(result, texture, self.img.image)
        except Exception as e:
            print(texture_path, e)
        # print(time.time() - t1)
        # self.save_result(self.img.saveDir)

    def boundary_handle(self, isTwinEdge=False):
        """边缘处理"""
        if self.boundarType == 2:
            return
        from bin.utils import decenterKernel, thickeningKernel
        # self.img.image[self.img.image == [255, 255, 255]] = [128, 128, 128]
        decenterKernel = decenterKernel / sum(sum(decenterKernel))
        meanImage = cv2.filter2D(self.img.image, -1, decenterKernel)
        boundary = cv2.imread(self.img.path)
        t = boundary == (255, 255, 255)
        dBoundary = np.where(t, meanImage, self.img.image)
        # if self.boundarType == 1:
        #     self.img.image = dBoundary
        #     self.img.pureImage = np.where(t, dBoundary, self.img.pureImage)
        #     return
        # k_size default 15, 15
        k_size = random.choice(range(5, 16, 2))
        gDBoundary = cv2.GaussianBlur(dBoundary, (k_size, k_size), 0, 0, cv2.BORDER_DEFAULT)
        # boundary_gaussan = cv2.blur(boundary, (5, 5))
        g = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
        diBoundary = cv2.dilate(boundary, g)
        gDiboundary = cv2.GaussianBlur(diBoundary, (15, 15), 0, 0, cv2.BORDER_DEFAULT)
        # gDiboundary = cv2.GaussianBlur(gDiboundary, (15, 15), 0, 0, cv2.BORDER_DEFAULT)
        # boundary = cv2.filter2D(boundary, -1, thickeningKernel)
        t = gDiboundary != (0, 0, 0)
        gDeBaBoundary = np.where(t, gDBoundary, gDiboundary)
        # cv2.imshow('12', mean_image)
        result = gDiboundary / 255 * gDeBaBoundary + (1 - gDiboundary / 255) * dBoundary
        result = result.astype(np.uint8)
        # cv2.imshow('dBoundary', dBoundary)
        # cv2.imshow('gDBoundary', gDBoundary)
        # cv2.imshow('gDeBaBoundary', gDeBaBoundary)
        # cv2.imshow('gDiboundary', gDiboundary)
        # cv2.imshow('result', result)
        # cv2.waitKey()
        t = boundary == (255, 255, 255)
        if not isTwinEdge:
            self.img.pureImage = np.where(t, dBoundary, self.img.pureImage)
        self.img.image = result

    # Mouse events
    def paintEvent(self, e):
        '''
        paint the red rect
        :param e:
        :return:
        '''
        if self.isSelect:
            painter = QPainter()
            painter.setPen(Qt.red)
            qLabelPos = self.centralWidget.mapTo(self, self.scrollArea.pos())
            hValue = self.scrollArea.horizontalScrollBar().value()
            vValue = self.scrollArea.verticalScrollBar().value()
            x = self.lastPoint.x() - qLabelPos.x() + hValue
            y = self.lastPoint.y() - qLabelPos.y() + vValue
            w = self.endPoint.x() - self.lastPoint.x()
            h = self.endPoint.y() - self.lastPoint.y()
            if self.isDrawing:
                qPixmap = QPixmap.copy(self.qPixmap)
                painter.begin(qPixmap)
                painter.setPen(Qt.red)
                painter.drawRect(x, y, w, h)
                painter.end()
                self.qLabel.setPixmap(qPixmap)

    def mousePressEvent(self, e):
        '''
        When the mouse left is pressed, the function run
        :param e:
        :return:
        '''
        qLabelPos = self.centralWidget.mapTo(self, self.scrollArea.pos())
        hValue = self.scrollArea.horizontalScrollBar().value()
        vValue = self.scrollArea.verticalScrollBar().value()
        t = e.localPos()
        x = int(t.x() - qLabelPos.x() + hValue)
        y = int(t.y() - qLabelPos.y() + vValue)
        print("%s, %s" % (x, y))
        print("%s, %s" % (x, y))

        if e.button() == Qt.LeftButton and self.img.path is not None:
            # Start draw
            self.lastPoint = e.localPos()
            self.endPoint = self.lastPoint
            self.isDrawing = True
            # Fill the image
            if 0 <= x < self.img.width and 0 <= y < self.img.height and self.isFilling:
                textureData = texture_db.query_random()
                self.fill_image(textureData.path, (x, y), (textureData.B, textureData.G, textureData.R))
                self.image_update()

    def mouseReleaseEvent(self, e):
        # 释放鼠标左键
        if e.button() == Qt.LeftButton:
            self.endPoint = e.localPos()
            # 重新绘制
            self.update()
            self.isDrawing = False
            if self.isGradient:
                qLabelPos = self.centralWidget.mapTo(self, self.scrollArea.pos())
                hValue = self.scrollArea.horizontalScrollBar().value()
                vValue = self.scrollArea.verticalScrollBar().value()
                s_x = int(self.lastPoint.x() - qLabelPos.x() + hValue)
                s_y = int(self.lastPoint.y() - qLabelPos.y() + vValue)
                e_x = int(self.endPoint.x() - qLabelPos.x() + hValue)
                e_y = int(self.endPoint.y() - qLabelPos.y() + vValue)
                # cv2.imshow('', self.img.image)
                # print(s_x, s_y, e_x, e_y)
                if s_x < e_x and s_y < e_y:
                    import matplotlib.pyplot as plt
                    cut = self.img.image[s_y:e_y, s_x: e_x, :]
                    height, width, depth = cut.shape
                    x = np.linspace(0, width, width)
                    legend = ['R', 'G', 'B']
                    # 第一行第一列图形
                    ax1 = plt.subplot(2, 1, 1)
                    ax2 = plt.subplot(2, 1, 2)
                    plt.sca(ax1)
                    for i, p in enumerate(cv2.split(cut)):
                        y = p[height // 2, :]
                        plt.plot(x, y, label=legend[i])
                        plt.title('Pixel color')
                        plt.legend()
                    # 第一行第二列图形
                    plt.sca(ax2)
                    print(cut.shape)
                    for i, p in enumerate(cv2.split(cv2.Sobel(cut, cv2.CV_64F, 1, 0, ksize=3))):
                        print(p.shape)
                        y = p[height // 2, :]
                        plt.plot(x, y, label=legend[i])
                        plt.title('Pixel gradient')
                        plt.legend()

                    plt.show()
                    # cv2.imshow("Blue", b)
                    # cv2.imshow("Red", r)
                    # cv2.imshow("Green", g)
                    # cv2.imshow('cut', cut)
                    # cv2.waitKey()

    def mouseMoveEvent(self, e):
        if e.buttons() and Qt.LeftButton:
            self.endPoint = e.localPos()
            self.update()

    # Create the slot function
    @pyqtSlot()
    def on_actionisSaveTwinEdge_triggered(self):
        '''
        select that if save the twins edge.
        :return:
        '''
        self.isSaveTwinEdge = self.actionisSaveTwinEdge.isChecked()

    @pyqtSlot()
    def on_actionExtension_triggered(self):
        '''
        Select the type of saving file
        :return:
        '''
        items = [".jpg", ".png", ".bmp"]
        value, ok = QInputDialog.getItem(self, "Select", "请选择保存格式:", items, 1, True)
        if ok:
            self.saveExtension = value

    @pyqtSlot()
    def on_actionBoundary_triggered(self):
        items = ["过渡边缘", "均值边缘", "白色边缘"]
        value, ok = QInputDialog.getItem(self, "Select", "请选择边缘类型:", items, 1, True)
        if ok:
            self.boundarType = items.index(value)

    @pyqtSlot()
    def on_actionbatchTag_triggered(self):
        if self.isPoint:
            total = len(self.img.imageList)
            step = 0
            self.progressBar.reset()
            for i in self.img.imageList:
                step += 1
                self.img.path = os.path.join(self.img.dir, i)
                self.img.imread(self.img.path)
                self.refill_image()
                QApplication.processEvents()
                self.progressBar.setValue(step / total * 100)
            QMessageBox.information(self, '消息', '标注完成！')
        else:
            QMessageBox.information(self, '消息', '请选择标注模式！')

    @pyqtSlot()
    def on_actionbacth_twinedge_triggered(self):
        '''
        generate the twins edge image by batch
        :return:
        '''
        if not self.isFilling:
            NotSelectFillError(self)
            return
        total = len(self.img.imageList)
        step = 0
        self.progressBar.reset()
        for i in self.img.imageList:
            step += 1
            self.img.path = os.path.join(self.img.dir, i)
            self.img.imread(self.img.path)
            self.gen_twinedge()
            self.boundarType = random.choice(range(0, 3, 2))
            self.boundary_handle(True)
            self.save_result(self.img.saveDir)
            QApplication.processEvents()
            self.progressBar.setValue(step / total * 100)
        QMessageBox.information(self, '消息', '双边缘生成完成！')

    @pyqtSlot()
    def on_actionJPEG_triggered(self):
        print('test')

    @pyqtSlot()
    def on_actiongradient_triggered(self):

        self.isGradient = self.actiongradient.isChecked()
        if self.isGradient:
            self.actionfill.setChecked(False)
            self.actiontag.setChecked(False)
            self.isFilling = self.isPoint = False

    @pyqtSlot()
    def on_actionfill_triggered(self):
        '''
        Can we fill the image
        :return:
        '''
        self.isFilling = self.actionfill.isChecked()
        if self.isFilling:
            self.actiongradient.setChecked(False)
            self.actiontag.setChecked(False)
            self.isGradient = self.isPoint = False

    @pyqtSlot()
    def on_actiontag_triggered(self):
        self.isPoint = self.actiontag.isChecked()
        if self.isPoint:
            self.actiongradient.setChecked(False)
            self.actionfill.setChecked(False)
            self.isGradient = self.isFilling = False

    @pyqtSlot()
    def on_actionbatch_triggered(self):
        '''
        Generate texture image by batch
        :return:
        '''
        # print('batch')
        if not self.isFilling:
            NotSelectFillError(self)
            return
        num, okPressed = QInputDialog.getInt(self, "Input", "batch:", 10, 0, 100, 1)
        if not okPressed:
            return
        total = len(self.img.imageList) * num
        step = 0
        self.progressBar.reset()
        for j in range(num):
            for i in self.img.imageList:
                step += 1
                self.img.path = os.path.join(self.img.dir, i)
                self.img.imread(self.img.path)
                try:
                    path = os.path.relpath(self.img.path)
                except:
                    QMessageBox.information(self, 'Error', '请选择目录下路径！')
                    return
                edge = edge_db.query_by_path(path)
                for point in point_db.query_by_edgeId(edge.id):
                    textureData = texture_db.query_random()
                    self.fill_image(textureData.path, (point.x, point.y), (textureData.B, textureData.G, textureData.R))
                self.boundarType = random.choice(range(3))
                self.boundary_handle()
                self.image_update()
                self.save_result(self.img.saveDir)
                self.progressBar.setValue(step / total * 100)
                # self.progress.setText("%s/%s" % (step, total))
                QApplication.processEvents()
        QMessageBox.information(self, '消息', '填充完成！')

    @pyqtSlot()
    def on_actionopen_triggered(self):
        self.open_image()

    @pyqtSlot()
    def on_actionopenFolder_triggered(self):
        self.select_folder()

    def open_image(self):
        '''
        Open one image, save the image_path as the path of image.
        :return:
        '''
        fname = QFileDialog.getOpenFileName(self, 'Open image', './')
        if fname[0]:
            self.img.get_image_list(os.path.dirname(fname[0]))
            self.img.path = fname[0]
            self.img.filename = os.path.basename(fname[0])
            self.img.dir = os.path.dirname(fname[0])
            self.img.imread(fname[0])
            self.image_update()

    def select_folder(self):
        '''
        Select folder
        :return:
        '''
        furl = QFileDialog.getExistingDirectory(self, 'Select folder', './')
        if furl:
            self.img.dir = furl
            if not self.img.get_image_list(furl):
                NotExistImage(self)
                return
            self.img.filename = self.img.imageList[0]
            self.img.path = os.path.join(self.img.dir, self.img.filename)
            self.img.imread(self.img.path)
            self.image_update()

    def enlarge_image(self):
        '''
        Enlarge the picture.
        :return:
        '''
        if self.img.path is None:
            return
        self.img.factor += .2
        self.img.enlarge()
        self.image_update()

    def lessen_image(self):
        '''
        Lessen the picture.
        :return:
        '''
        if self.img.path is None:
            return
        self.img.factor -= .2
        self.img.lessen()
        self.image_update()

    def next_image(self):
        '''
        Load next image
        :return:
        '''
        if self.img.path is None:
            return
        imgId = self.img.imageList.index(self.img.filename)
        if imgId > len(self.img.imageList) - 2:
            QMessageBox.information(self, '消息', '最后一张图片啦！')
            return
        else:
            self.img.filename = self.img.imageList[imgId + 1]
            self.img.path = os.path.join(self.img.dir, self.img.filename)
            self.img.image = self.img.imread(self.img.path)
            self.image_update()

    def last_image(self):
        '''
        Load last image
        :return:
        '''
        if self.img.path is None:
            PathIsInvalid(self)
            return
        imgId = self.img.imageList.index(self.img.filename)
        if imgId < 1:
            QMessageBox.information(self, '消息', '前面已经没有图片啦！')
            return
        else:
            self.img.filename = self.img.imageList[imgId - 1]
            self.img.path = os.path.join(self.img.dir, self.img.filename)
            self.img.image = self.img.imread(self.img.path)
            self.image_update()

    def refill_image(self):
        '''
        Point the image
        :return:
        '''
        if not self.isPoint:
            NotSelectPointError(self)
            return
        try:
            path = os.path.relpath(self.img.path)
        except:
            QMessageBox.information(self, 'Error', '请选择目录下路径！')
            return
        if edge_db.query_by_path(path):
            QMessageBox.information(self, '消息', '已经标注！')
            return
        else:
            edge_db.insert(edge_db.Edge(path=path))
            edge = edge_db.query_by_path(path)
        try:
            points = []
            for x in range(self.img.height):
                for y in range(self.img.width):
                    if all(self.img.image[x, y] == np.zeros((3,))):
                        mask = np.zeros([self.img.height + 2, self.img.width + 2], np.uint8)
                        color = (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))
                        cv2.floodFill(self.img.image, mask, (y, x), color, cv2.FLOODFILL_FIXED_RANGE)
                        xy = []
                        for i in range(self.img.height):
                            for j in range(self.img.width):
                                if all(self.img.image[i, j] == color):
                                    xy.append((j, i))
                        # self.img.image[self.img.image != 244] = 0
                        # print(xy)
                        a, b = random.choice(xy)
                        points.append(point_db.Point(edge_id=edge.id, x=a, y=b))
                        # cv2.circle(self.img.image, xy, 5, (0, 255, 255), 3)
                        # print(xy)
            self.image_update()
            if points:
                point_db.insert(points)
            else:
                edge_db.delete(edge)
                PointIsFailError(self)
        except Exception as e:
            edge_db.delete(edge)
            QMessageBox.information(self, 'Exception', e)

    def gen_twinedge(self):
        '''
        generate twins edge
        :return:
        '''
        if not self.isFilling:
            NotSelectFillError(self)
            return
        if self.img.path:
            path = os.path.relpath(self.img.path)
        else:
            QMessageBox.information(self, '消息', '请选择图片！')
            return
        edge = edge_db.query_by_path(path)
        # edgeIndex = 0
        # one = (1, 1, 1)
        # for point in point_db.query_by_edgeId(edge.id):
        #     textureData = texture_db.query_random()
        #     # edgeIndex += 1
        #     # color = (edgeIndex, edgeIndex, edgeIndex)
        #     color = (textureData.B, textureData.G, textureData.R)
        #     # fill pure image
        #     mask = np.zeros([self.img.height + 2, self.img.width + 2], np.uint8)
        #     cv2.floodFill(self.img.pureImage, mask, (point.x, point.y), WHITE, cv2.FLOODFILL_FIXED_RANGE)
        #     mask = np.zeros([self.img.height + 2, self.img.width + 2], np.uint8)
        #     cv2.floodFill(self.img.pureImage, mask, (point.x, point.y), color, cv2.FLOODFILL_FIXED_RANGE)
        #
        #     # fill original image
        #     mask = np.zeros([self.img.height + 2, self.img.width + 2], np.uint8)
        #     cv2.floodFill(self.img.image, mask, (point.x, point.y), WHITE, cv2.FLOODFILL_FIXED_RANGE)
        #     mask = np.zeros([self.img.height + 2, self.img.width + 2], np.uint8)
        #     cv2.floodFill(self.img.image, mask, (point.x, point.y), one, cv2.FLOODFILL_FIXED_RANGE)
        #
        #     result = self.img.image == one
        #     texture = cv2.imread(textureData.path)
        #     texture = cv2.cvtColor(texture, cv2.COLOR_BGR2RGB)
        #     texture = texture[0: self.img.height, 0:self.img.width, :]
        #     self.img.image = np.where(result, texture, self.img.image)

        for point in point_db.query_by_edgeId(edge.id):
            textureData = texture_db.query_random()
            self.fill_image(textureData.path, (point.x, point.y), (textureData.B, textureData.G, textureData.R), True)

        if self.isSaveTwinEdge:
            image = self.img.pureImage.copy()
            for x in range(1, self.img.height - 1):
                for y in range(1, self.img.width - 1):
                    for i in [-1, 0, 1]:
                        for j in [-1, 0, 1]:
                            # print(self.img.image[x + i, y + j].any())
                            if self.img.pureImage[x + i, y + j, 0] != self.img.pureImage[x, y, 0]:
                                # print(image[x, y])
                                image.itemset((x, y, 1), 0)
                                image.itemset((x, y, 2), 0)
                                break
            self.img.pureImage = image
        self.image_update()

    def finash(self):
        '''
        Save the image
        :return:
        '''
        if self.isFilling:
            self.boundary_handle()
        self.save_result(self.img.saveDir)
        self.image_update()
        QMessageBox.information(self, '消息', '图片保存！')


if __name__ == '__main__':
    app = QApplication(sys.argv)
    MainWindow = MainWindow()
    # ui = texturefiller.Ui_TextureFillClass()
    # ui.setupUi(MainWindow)
    MainWindow.show()
    sys.exit(app.exec_())
